//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ListFastaData.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <zlib.h>

#include <fstream>
#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define MAX_SIZE 500000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListFastaData::ListFastaData () {

  this->filenameIn          = new String ();
  this->data                = new TListE <FastaData> ();
  this->toString            = new String ();

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListFastaData::ListFastaData (const ListFastaData& listFastaData) {

  this->filenameIn          = new String (listFastaData.filenameIn);
  this->data                = new TListE <FastaData> (listFastaData.data);
  this->toString            = new String (listFastaData.toString);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListFastaData::ListFastaData (const ListFastaData* listFastaData) {

  this->filenameIn          = new String (listFastaData->filenameIn);
  this->data                = new TListE <FastaData> (listFastaData->data);
  this->toString            = new String (listFastaData->toString);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListFastaData::~ListFastaData () {

  if (this->filenameIn) delete this->filenameIn;
  if (this->data)       delete this->data;
  if (this->toString)   delete this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListFastaData::FilenameIn (String* filenameIn) {

  if (filenameIn)
    *(this->filenameIn) = *filenameIn;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListFastaData::Data (TListE <FastaData>* data) {

  if (data)
    *(this->data) = *data;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//

String* ListFastaData::FilenameIn (void) {

  return this->filenameIn;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <FastaData>* ListFastaData::Data (void) {

  return this->data;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListFastaData::LoadData (void) {

  if (!this->filenameIn || !this->filenameIn->Length()) return false;
  
  bool isGZFile = (this->filenameIn->Contain("gz"))?1:0;
  
  fstream file;
  gzFile  zipFile;
  
  char    buffer [MAX_SIZE + 1];
  String* data = new String ();
  
  if (isGZFile) zipFile = gzopen (this->filenameIn->Out(), "rb9");
  else          file.open (this->filenameIn->Out(), fstream::in);
  
  while (!((isGZFile)?gzeof(zipFile):file.eof())) {
    
    if (isGZFile) gzgets(zipFile, buffer, MAX_SIZE);
    else          file.getline(buffer, MAX_SIZE);
    
    if (!strlen(buffer)) continue;
    
    data->Add(buffer);
    data->Add("\n");
    
    if (buffer[0] != '>') {
      
      FastaData* newFastaData = new FastaData ();
      
      if (newFastaData->ReadFromString(data)) 
        this->data->Add(newFastaData);
      else 
        delete newFastaData;
      
      data->In("");
      
    }
    
  }
  
  if (isGZFile) gzclose(zipFile);
  else          file.close();
  
  if (data)     delete data;
   
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListFastaData::ToString (void) {
 
  this->toString->In("");

  this->data->SetInitial();
  while (this->data->SetNext()) {
    
    FastaData* currentFastaData = this->data->GetCurrent();
    
    this->toString->Add(currentFastaData->ToString()->Out());
    this->toString->Add("\n");

  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListFastaData ListFastaData::operator= (const ListFastaData& listFastaData) {

  *(this->filenameIn) = *(listFastaData.filenameIn);
  *(this->data)       = *(listFastaData.data);
  *(this->toString)   = *(listFastaData.toString);

  return *this;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
